package com.lsh.oms.core.records;

import com.google.common.collect.Lists;
import com.lsh.oms.core.dao.other.ReturnResultMapper;
import com.lsh.oms.core.records.core.ReturnResult;
import com.lsh.oms.core.service.tool.Criteria;
import com.lsh.oms.core.service.tool.Criterias;
import com.lsh.oms.core.service.tool.Pageable;
import com.lsh.oms.core.service.tool.Summaries;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Stream;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;

@Component
public class ReturnResultRepository implements com.lsh.oms.core.records.core.ReturnResultRepository {

    @Resource
    private ReturnResultMapper mapper;

    @Override
    public Pageable query(Criteria criteria, long page, long pageLimit) {
        Long count = mapper.countBaseOnCriteria(criteria);
        List<ReturnResult> result = count > 0
                ? mapper.findBaseOnCriteria(criteria, Pageable.start(page, pageLimit), pageLimit)
                : Collections.emptyList();
        fillDetails(criteria, result);
        return new Pageable<>(result, page, pageLimit, count);
    }

    private void fillDetails(Criteria criteria, List<ReturnResult> records) {
        if (Criterias.detailsRequired(criteria)) {
            Map<Long, List<ReturnResult.ReturnResultDetail>> group = findDetails(records.stream().map(ReturnResult::id).collect(toList()))
                    .stream().collect(groupingBy($ -> $.returnResultId()));
            records.forEach($ -> ((ReturnResultRecord) $).details = group.get($.id()));
        }
    }

    @Override
    public Optional<ReturnResult> find(Long id) {
        ReturnResult order = mapper.findById(id);
        if (order == null) {
            return Optional.empty();
        }
        ((ReturnResultRecord) order).details = findDetails(Lists.newArrayList(id));
        return Optional.of(order);
    }

    private List<ReturnResult.ReturnResultDetail> findDetails(Collection<Long> returnIds) {
        return returnIds.isEmpty() ? Collections.emptyList() : mapper.findDetails(returnIds);
    }

    @Override
    public Map<String, Long> summary(Criteria criteria) {
        criteria.remove("status");
        Map<String, Long> result = Summaries.enhance(mapper.groupByStatus(criteria));
        Stream.of(ReturnResult.Status.values()).forEach($ -> {
            String key = Summaries.key($.name());
            if (!result.containsKey(key)) {
                result.put(key, 0L);
            }
        });
        return result;
    }
}
